/*
 * @FileName: 
 * @Version: 
 * @Author: 王杨洋
 * @Date: 2021-03-26 20:13:54
 */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdarg.h>
#include "../include/message.h"
#include "../include/device_manage.h"

static int GetChkSum(char* data, int dataLen)
{
	int sum = 0;
	for(int i = 0; i < dataLen; i++)
	{
		sum += data[i];
	}
	return sum;
}

void AddDevice(int sockfd, const char *username, int nameLen)
{
    MsgStruct msg;
    int curSeq = 0;
    msg.version = MSG_VERSION;
	msg.header_len = MSG_HEADER_STABLE_LEN;
	msg.encrypt_type = MSG_ENCRYPT_NONE;
	msg.protocol_type = MSG_PROTOCOL_C2S;
	msg.data_type = MSG_DATA_ADD_DEVICE;
	msg.seq_num = curSeq;
	msg.frag_flag = MSG_FLAG_FRAG_NO;
	msg.frag_offset = 0;
	msg.total_len = MSG_HEADER_STABLE_LEN;
	msg.source_addr = 0x7F000001;
	msg.target_addr = 0x7F000001;
	msg.header_chk = GetChkSum((char*)(&msg), MSG_HEADER_STABLE_LEN);
    strcpy(msg.data, username);
    msg.custom1 = nameLen;
    if(send(sockfd, &msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("fail to send.\n");
		return;
	}
	printf("send ok!\n");
    memset(&msg, 0x0, sizeof(MsgStruct));
    while (recv(sockfd, &msg, sizeof(msg), 0) > 0)
	{
        //Check Some Param
	    if (msg.version != MSG_VERSION) {
		    printf("version error:0x%x.\n", msg.version);
		    return;		
	    }
	    if (msg.encrypt_type != MSG_ENCRYPT_NONE) {
		    printf("encrypt_type error:0x%x.\n", msg.encrypt_type);
		    return;		
	    }
	    if (msg.protocol_type != MSG_PROTOCOL_S2C) {
		    printf("protocol_type error:0x%x.\n", msg.protocol_type);
		    return;	
	    }
	    if (msg.frag_flag != MSG_FLAG_FRAG_NO) {
		    printf("frag_flag error:0x%x.\n", msg.frag_flag);
		    return;
	    }
	    if (msg.header_chk != GetChkSum((char*)(&msg), msg.header_len)) {
		    printf("header_chk error:0x%x.\n", msg.header_chk);
		    return;
	    }
		//请求失败，打印错误信息
		if (msg.custom1 == MSG_CUSTOM1_ADD_DEVICE_FAILURE) {
			switch (msg.custom2) {
				case MSG_CUSTOM2_ADD_DEVICE_FAILURE_MACADDR: {
					printf("mac error.\n");
					return;
					} break;
				case MSG_CUSTOM2_ADD_DEVICE_FAILURE_ALREADY: {
					printf("device already add.\n");
					return;
					} break;
				case MSG_CUSTOM2_ADD_DEVICE_FAILURE_CONNECT: {
					printf("connect error.\n");
					return;
					} break;
				case MSG_CUSTOM2_ADD_DEVICE_FAILURE_DATABASE: {
					printf("database error.\n");
					return;
					} break;
				case MSG_CUSTOM2_ADD_DEVICE_FAILURE_DEVICE: {
					printf("device error.\n");
					return;
					} break;
				default: break;
			}
		}
        if (msg.custom1 == MSG_CUSTOM1_ADD_DEVICE_SUCCESS) {
			printf("add device success\n");
            return;
        }
        printf("data invalid!\n");
        memset(&msg, 0x0, sizeof(MsgStruct));
    }
    return;
}

// data 为返回查询结果
void QueryDevice(int sockfd, const char *username, int nameLen, int *deviceNum, char *data)
{
    MsgStruct msg;
    int curSeq = 0;
    msg.version = MSG_VERSION;
	msg.header_len = MSG_HEADER_STABLE_LEN;
	msg.encrypt_type = MSG_ENCRYPT_NONE;
	msg.protocol_type = MSG_PROTOCOL_C2S;
	msg.data_type = MSG_DATA_QUERY_DEVICE;
	msg.seq_num = curSeq;
	msg.frag_flag = MSG_FLAG_FRAG_NO;
	msg.frag_offset = 0;
	msg.total_len = MSG_HEADER_STABLE_LEN;
	msg.source_addr = 0x7F000001;
	msg.target_addr = 0x7F000001;
	msg.header_chk = GetChkSum((char*)(&msg), MSG_HEADER_STABLE_LEN);
    strcpy(msg.data, username);
    msg.custom1 = nameLen;
    if(send(sockfd, &msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("fail to send.\n");
		return;
	}
	printf("send ok!\n");
    memset(&msg, 0x0, sizeof(MsgStruct));
    while (recv(sockfd, &msg, sizeof(msg), 0) > 0)
	{
        //Check Some Param
	    if (msg.version != MSG_VERSION) {
		    printf("version error:0x%x.\n", msg.version);
		    return;		
	    }
	    if (msg.encrypt_type != MSG_ENCRYPT_NONE) {
		    printf("encrypt_type error:0x%x.\n", msg.encrypt_type);
		    return;		
	    }
	    if (msg.protocol_type != MSG_PROTOCOL_S2C) {
		    printf("protocol_type error:0x%x.\n", msg.protocol_type);
		    return;	
	    }
	    if (msg.frag_flag != MSG_FLAG_FRAG_NO) {
		    printf("frag_flag error:0x%x.\n", msg.frag_flag);
		    return;
	    }
	    if (msg.header_chk != GetChkSum((char*)(&msg), msg.header_len)) {
		    printf("header_chk error:0x%x.\n", msg.header_chk);
		    return;
	    }
		//请求失败，打印错误信息
		if (msg.custom1 == MSG_CUSTOM1_QUERY_DEVICE_FAILURE) {
			switch (msg.custom2) {
				case MSG_CUSTOM2_QUERY_DEVICE_FAILURE_ACCOUNT: {
					printf("user don't login.\n");
					return;
					} break;
				case MSG_CUSTOM2_QUERY_DEVICE_FAILURE_CONNECT: {
					printf("connect error.\n");
					return;
					} break;
				case MSG_CUSTOM2_QUERY_DEVICE_FAILURE_DATABASE: {
					printf("database error.\n");
					return;
					} break;
				default: break;
			}
		}
        if (msg.custom1 == MSG_CUSTOM1_QUERY_DEVICE_SUCCESS) {
			printf("query device success\n");
			*deviceNum = msg.custom2;
			strcpy(data, msg.data);
            return;
        }
        printf("data invalid!\n");
        memset(&msg, 0x0, sizeof(MsgStruct));
    }
    return;
}

void NameDevice(int sockfd, const char *username, int nameLen, const char *mac, const char *devicename, int deviceNameLen)
{
    MsgStruct msg;
    int curSeq = 0;
    msg.version = MSG_VERSION;
	msg.header_len = MSG_HEADER_STABLE_LEN;
	msg.encrypt_type = MSG_ENCRYPT_NONE;
	msg.protocol_type = MSG_PROTOCOL_C2S;
	msg.data_type = MSG_DATA_NAME_DEVICE;
	msg.seq_num = curSeq;
	msg.frag_flag = MSG_FLAG_FRAG_NO;
	msg.frag_offset = 0;
	msg.total_len = MSG_HEADER_STABLE_LEN;
	msg.source_addr = 0x7F000001;
	msg.target_addr = 0x7F000001;
	msg.header_chk = GetChkSum((char*)(&msg), MSG_HEADER_STABLE_LEN);
    strncpy(msg.data, username, nameLen);
	strncpy(msg.data + nameLen, mac, 23);
	strncpy(msg.data + nameLen + 23, devicename, deviceNameLen);
    msg.custom1 = nameLen;
	msg.custom2 = deviceNameLen;
    if(send(sockfd, &msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("fail to send.\n");
		return;
	}
	printf("send ok!\n");
    memset(&msg, 0x0, sizeof(MsgStruct));
    while (recv(sockfd, &msg, sizeof(msg), 0) > 0)
	{
        //Check Some Param
	    if (msg.version != MSG_VERSION) {
		    printf("version error:0x%x.\n", msg.version);
		    return;		
	    }
	    if (msg.encrypt_type != MSG_ENCRYPT_NONE) {
		    printf("encrypt_type error:0x%x.\n", msg.encrypt_type);
		    return;		
	    }
	    if (msg.protocol_type != MSG_PROTOCOL_S2C) {
		    printf("protocol_type error:0x%x.\n", msg.protocol_type);
		    return;	
	    }
	    if (msg.frag_flag != MSG_FLAG_FRAG_NO) {
		    printf("frag_flag error:0x%x.\n", msg.frag_flag);
		    return;
	    }
	    if (msg.header_chk != GetChkSum((char*)(&msg), msg.header_len)) {
		    printf("header_chk error:0x%x.\n", msg.header_chk);
		    return;
	    }
		//请求失败，打印错误信息
		if (msg.custom1 == MSG_CUSTOM1_NAME_DEVICE_FAILURE) {
			switch (msg.custom2) {
				case MSG_CUSTOM2_NAME_DEVICE_FAILURE_FORMAT: {
					printf("devicename format error.\n");
					return;
					} break;
				case MSG_CUSTOM2_NAME_DEVICE_FAILURE_CONNECT: {
					printf("connect error.\n");
					return;
					} break;
				case MSG_CUSTOM2_NAME_DEVICE_FAILURE_DATABASE: {
					printf("database error.\n");
					return;
					} break;
				default: break;
			}
		}
        if (msg.custom1 == MSG_CUSTOM1_NAME_DEVICE_SUCCESS) {
			printf("name device success\n");
            return;
        }
        printf("data invalid!\n");
        memset(&msg, 0x0, sizeof(MsgStruct));
    }
    return;
}

// commandType = msg->data_type, deviceType = custom1, command = custom2, 可变参数为设置温度，风力时的额外参数
void SendDeviceCommand(int sockfd, int commandType, int deviceType, int command, const char *mac, ...)
{
	va_list CustomArg;
	va_start(CustomArg, mac);
    MsgStruct msg;
    int curSeq = 0;
    msg.version = MSG_VERSION;
	msg.header_len = MSG_HEADER_STABLE_LEN;
	msg.encrypt_type = MSG_ENCRYPT_NONE;
	msg.protocol_type = MSG_PROTOCOL_C2S;
	msg.data_type = commandType;
	msg.seq_num = curSeq;
	msg.frag_flag = MSG_FLAG_FRAG_NO;
	msg.frag_offset = 0;
	msg.total_len = MSG_HEADER_STABLE_LEN;
	msg.source_addr = 0x7F000001;
	msg.target_addr = 0x7F000001;
	msg.header_chk = GetChkSum((char*)(&msg), MSG_HEADER_STABLE_LEN);
    strcpy(msg.data, mac);
	msg.data[23] = (char)va_arg(CustomArg, int);
	va_end(CustomArg);
    msg.custom1 = deviceType;
	msg.custom2 = command;
    if(send(sockfd, &msg, sizeof(MsgStruct), 0) < 0)
	{
		perror("fail to send");
		return;
	}
	printf("send ok!\n");
    memset(&msg, 0x0, sizeof(MsgStruct));
    while (recv(sockfd, &msg, sizeof(msg), 0) > 0)
	{
        //Check Some Param
	    if (msg.version != MSG_VERSION) {
		    printf("version error:0x%x.\n", msg.version);
		    return;		
	    }
	    if (msg.encrypt_type != MSG_ENCRYPT_NONE) {
		    printf("encrypt_type error:0x%x.\n", msg.encrypt_type);
		    return;		
	    }
	    if (msg.protocol_type != MSG_PROTOCOL_S2C) {
		    printf("protocol_type error:0x%x.\n", msg.protocol_type);
		    return;	
	    }
	    if (msg.frag_flag != MSG_FLAG_FRAG_NO) {
		    printf("frag_flag error:0x%x.\n", msg.frag_flag);
		    return;
	    }
	    if (msg.header_chk != GetChkSum((char*)(&msg), msg.header_len)) {
		    printf("header_chk error:0x%x.\n", msg.header_chk);
		    return;
	    }
		//请求失败，打印错误信息
		if (commandType == MSG_DATA_SET_DEVICE_STATUS)
		{
			if (msg.custom1 == MSG_CUSTOM1_SET_DEVICE_STATUS_SUCCESS) {
				printf("set device success\n");
        	    return;
        	}
			if (msg.custom1 == MSG_CUSTOM1_SET_DEVICE_STATUS_FAILURE) {
				switch (msg.custom2)
				{
					case MSG_CUSTOM2_SET_DEVICE_STATUS_FAILURE_MACADDR: {printf("macaddr error.\n"); return;} break;
					case MSG_CUSTOM2_SET_DEVICE_STATUS_FAILURE_COMMAND: {printf("command error.\n"); return;} break;
					case MSG_CUSTOM2_SET_DEVICE_STATUS_FAILURE_CONNECT: {printf("connect error.\n"); return;} break;
					case MSG_CUSTOM2_SET_DEVICE_STATUS_FAILURE_DEVICE: {printf("device error.\n"); return;} break;
					default: break;
				}
			}
		}
		else
		{
			if (msg.custom1 == MSG_CUSTOM1_GET_DEVICE_STATUS_SUCCESS) 
			{
				printf("get device success.\n");
				switch (deviceType)
				{
					case MSG_CUSTOM1_GET_DEVICE_AIRCONDITION:
					{
						switch (command)
						{
							// 开关状态和制冷制热状态结果参考设置命令
							case MSG_CUSTOM2_GET_DEVICE_AIR_ONOFF: {printf("switch : %s\n", msg.data);} break;
							case MSG_CUSTOM2_GET_DEVICE_AIR_HOTCOLD: {printf("state : %s\n", msg.data);} break;
							case MSG_CUSTOM2_GET_DEVICE_AIR_TEMP: {printf("temperature : %s\n", msg.data);} break;
							case MSG_CUSTOM2_GET_DEVICE_AIR_WIND: {printf("wind : %s\n", msg.data);} break;
							default: break;
						}
					} break;
					case MSG_CUSTOM1_GET_DEVICE_REFRIGERATOR:
					{
						switch (command)
						{
							case MSG_CUSTOM2_GET_DEVICE_REF_FRESH: {printf("fresh : %s\n", msg.data);} break;
							case MSG_CUSTOM2_GET_DEVICE_REF_FREEZ: {printf("freez : %s\n", msg.data);} break;
							default: break;
						}
					} break;
					default: break;
				}
        	    return;
        	}
			if (msg.custom1 == MSG_CUSTOM1_GET_DEVICE_STATUS_FAILURE) {
				switch (msg.custom2)
				{
					case MSG_CUSTOM2_GET_DEVICE_STATUS_FAILURE_MACADDR: {printf("macaddr error.\n"); return;} break;
					case MSG_CUSTOM2_GET_DEVICE_STATUS_FAILURE_COMMAND: {printf("command error.\n"); return;} break;
					case MSG_CUSTOM2_GET_DEVICE_STATUS_FAILURE_CONNECT: {printf("connect error.\n"); return;} break;
					case MSG_CUSTOM2_GET_DEVICE_STATUS_FAILURE_DEVICE : {printf("device error.\n"); return;} break;
					default: break;
				}
			}
		}

        printf("data invalid!\n");
        memset(&msg, 0x0, sizeof(MsgStruct));
    }
    return;
}

